/*
 * @Author: wuqingchun
 * @Date: 2024-04-15 19:10:29
 * @Description:  std::bind 的使用
 * @LastEditors: wuqingchun
 * @LastEditTime: 2024-04-15 19:48:12
 */
#ifndef __STD_BIND_H__
#define __STD_BIND_H__

#include <iostream>
#include <functional>

inline int add(int a, int b)
{
    std::cout << "a: " << a << ", b: " << b << std::endl;
    return a + b;
}

class Adder
{
public:
    int incr(int iStep)
    {
        m_iResult += iStep;

        return m_iResult;
    }

    int add(int a, int b)
    {
        m_iResult = a + b;

        return m_iResult;
    }
private:
    int m_iResult {0};
};

class TestSTDBind
{
public:
    void BindNormalFunction()
    {
        std::function<int(int)> objFunc = std::bind(add, 10, std::placeholders::_1);
        std::cout << objFunc(20) << std::endl;

        // bind第一个参数传入一个函数、函数指针、lamda表达式、类的成员函数都是可以的，这里注意，
        // 如果是类的成员函数，则需要再类的作用域前加上&，第二个占位符需要注意，如果不是类的成员函数，那么直接要么是一个参数，例如10，或者std::placeholders::_1（由调用bind返回值时传入），如果是类的成员函数，第二个参数是实例化的类对象，第三个参数开始才是函数的输入参数。也可参考std::function对于类的成员函数的调用。

        std::function<int(int, int)> objFunc1 = std::bind(add, 1, std::placeholders::_1);
        std::cout << objFunc1(1, 3) << std::endl;

        std::function<int(int, int)> objFunc2 = std::bind(add, 100, std::placeholders::_2);
        std::cout << objFunc2(100, 300) << std::endl;

        std::function<int(int, int)> objFunc3 = std::bind(add, std::placeholders::_1, std::placeholders::_2);
        std::cout << objFunc3(11, 12) << std::endl;
    }

    void BindClassMemberFunction()
    {
        Adder objAdder;

        // bind 绑定类成员函数时，第一个参数表示对象的成员函数的指针，第二个参数表示对象的地址。
        // 必须显式地指定&Adder::add，因为编译器不会将对象的成员函数隐式转换成函数指针，所以必须在 Adder::add 前添加&；
        std::function<int(int, int)> objFunc = std::bind(&Adder::add, &objAdder, std::placeholders::_1, std::placeholders::_2);
        std::cout << objFunc(1, 2) << std::endl;
    }

    void BindLambda()
    {
        auto LambdaFunc = std::bind([](int a, int b)->int{
            std::cout << "lambda expression" << std::endl;
            return a+b;
        }, std::placeholders::_1, std::placeholders::_2);

        std::cout << LambdaFunc(1, 2) << std::endl;
    }
};


#endif //__STD_BIND_H__